<?php
namespace lib\JhWechat;

/**
 * 网页授权
 * @Auth: JH <hu@lunaz.cn>
 * Class Oauth
 * @package lib\JhWechat
 */
class Oauth extends Base
{

    /**
     * @param array $options
     */
    function __construct(array $options = array())
    {
        if ($options) {
            parent::$config = $options;
        }
        parent::__construct();
    }

    /**
     * step 1
     * 不弹出授权页面，直接跳转，只获取open id，
     *
     * @param string $callback
     * @param string $state
     * 微信服务器带上code重定向到$callback地址后，可通过code换取网页授权access_token
     * callback_url?code=CODE&state=STATE。
     */
    function onlyOpenId($callback, $state = 'abc123')
    {
        $this->to($this->getCode($callback, $state, 'snsapi_base'));
    }

    /**
     * step 1
     * 弹出授权页面，即使在未关注的情况下，只要用户授权，就能通过OPENID获取其信息
     *
     * @param string $callback
     * @param string $state
     * 用户授权后，微信服务器带上code重定向到$callback地址后，可通过code换取网页授权access_token
     * callback_url?code=CODE&state=STATE。
     */
    function fullUserInfo($callback, $state = 'abc123')
    {
        $this->to($this->getCode($callback, $state, 'snsapi_userinfo'));
    }

    /**
     * step 2
     * 通过code或ACCESS_TOKEN获取用户信息
     *
     * @param string $code
     * @param string $token
     *
     * @return array|false
     * <pre>
     * Array(
     *      [access_token] => ACCESS_TOKEN
     *      [expires_in] => 7200
     *      [refresh_token] => REFRESH_TOKEN
     *      [openid] => OPENID
     *      [scope] => SCOPE
     *      [nickname] => NICKNAME
     *      [sex] => 1
     *      [province] => PROVINCE
     *      [city] => CITY
     *      [country] => COUNTRY
     *      [headimgurl] => http://wx.qlogo.cn/mmopen/g3MonUZtNHk/46
     *      [privilege] => Array(
     *                      [0] => PRIVILEGE1
     *                      [1] => PRIVILEGE2
     *                      )
     *      [unionid] => o6_bmasdasdsad6_2sgVt7hMZOPfL
     * )
     * </pre>
     * @throws Exception
     */
    function userInfo($code = '', $token = '')
    {
        $result = array();
        if ($code && !$token) { //如果传入token值，不去获取access_token
            $result = $this->http(
                $this->makeUrl(
                    '/sns/oauth2/access_token',
                    array(
                        'appid' => parent::$config['appId'],
                        'secret' => parent::$config['appSecret'],
                        'code' => $code,
                        'grant_type' => 'authorization_code'
                    ),
                    parent::API_BASE
                )
            );
            if (isset($result['access_token'])) {
                if ($result['scope'] == 'snsapi_base') { //如果scope为snsapi_base，没必要去获取用户详细信息
                    return $result;
                }
                $token = $result['access_token'];
            } else {
                return false;
            }
        }

        $info = $this->http(
            $this->makeUrl(
                '/sns/userinfo',
                array(
                    'access_token' => $token,
                    'openid' => $result['openid'],
                    'lang' => 'zh_CN'
                ),
                parent::API_BASE
            )
        );
        if ($info) {
            return ($result + $info);
        }
        return $info;
    }

    /**
     * 验证数据是否合法
     *
     * @param string $access_token
     * @param string $open_id
     *
     * @return bool
     * @throws Exception
     */
    function valid($access_token, $open_id)
    {
        return $this->http(
            $this->makeUrl('/sns/auth',
                array('access_token' => $access_token, 'openid' => $open_id),
                parent::API_BASE)
        );
    }

    /**
     * @param $refresh_token
     *
     * @return array|false
     * <pre>
     * Array(
     *      [access_token] => ACCESS_TOKEN
     *      [expires_in] => 7200
     *      [refresh_token] => REFRESH_TOKEN
     *      [openid] => OPENID
     *      [scope] => SCOPE
     * )
     * </pre>
     * @throws Exception
     */
    function refreshToken($refresh_token)
    {
        return $this->http(
            $this->makeUrl(
                '/sns/oauth2/refresh_token',
                array(
                    'appid' => parent::$config['appId'],
                    'grant_type' => 'refresh_token',
                    'refresh_token' => $refresh_token
                ),
                parent::API_BASE
            )
        );
    }

    /**
     * 302跳转
     *
     * @param string $url
     */
    private function to($url)
    {
        header("Location: {$url}");
        exit(0);
    }

    /**
     * @param string $callback
     * @param string $state
     * @param string $scope
     *
     * @return string
     */
    private function getCode($callback, $state, $scope)
    {
        return $this->makeUrl(
            '/connect/oauth2/authorize',
            array(
                'appid' => parent::$config['appId'],
                'redirect_uri' => urlencode($callback),
                'response_type' => 'code',
                'scope' => $scope,
                'state' => $state
            ),
            'https://open.weixin.qq.com'
        ) . '#wechat_redirect';
    }
}
